﻿using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System.Globalization;
using System.Runtime.InteropServices;
using System.ComponentModel.Design;
using Microsoft.Win32;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.OLE.Interop;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.SharePoint;
using EnvDTE;
using EnvDTE80;

namespace SPVSX.Common
{
    /// <summary>
    /// TODO: Comment
    /// 
    /// This code is a WIP and is in need of improved commenting, exception handling, and potentially
    /// factoring.  Please be nice.
    /// 
    /// Though this code is Open Source, in good faith it is requested that you consult the original author(s)
    /// before changing or re-using it for any public endeavour intended to provide similar functionality, or
    /// to fix simple bugs.  In other words, if you want to create SPVSX2, please let us know first.
    /// </summary>
    /// <remarks>@author Matt Smith, http://blog.mattsmith.co.nz</remarks>  
    public class OutputWindowLogger
    {
        private static OutputWindowLogger singleton = null;
        
        private OutputWindowPane buildPane = null;
        private OutputWindow outputWindow = null;
        private DTE2 dte2 = null;

        public OutputWindow OutputWindow
        {
            get
            {
                if (outputWindow == null)
                {
                    outputWindow = dte2.ToolWindows.OutputWindow;
                }
                return outputWindow;
            }
        }

        public OutputWindowPane OutputWindowPane
        {
            get
            {
                if (buildPane == null)
                {
                    string buildName = "Build"; // TODO: Need to localise this.
                    buildPane = this.OutputWindow.OutputWindowPanes.Item(buildName);
                }
                return buildPane;
            }
        }

        public static OutputWindowLogger Instance
        {
            get
            {
                if (singleton == null)
                {
                    throw new Exception("OutputWindowLogger has not been initialized.");
                }
                return singleton;
            }
        }

        public static void InitializeInstance(DTE2 dte2)
        {
            // Workaround used to get a valid DTE object into the singleton.  This singleton thus
            // must be initialized before being used.
            singleton = new OutputWindowLogger(dte2);
        }

        private OutputWindowLogger(DTE2 dte2)
        {
            this.dte2 = dte2;
        }

        public void WriteLine(string message, LogCategory category)
        {
            OutputWindowPane pane = this.OutputWindowPane;
            if (pane == null)
            {
                return;
            }

            // This is a real nasty piece of work - we are bypassing the SP tooling's logger in order to get
            // full access to manipulate the log window at all times.  However, we need to indent to match the
            // OOTB functionality if we are executing a standard deployment.
            string prefix = 
                dte2.Solution.SolutionBuild.BuildState == vsBuildState.vsBuildStateInProgress ? "  " : "";
            pane.OutputString(prefix + message + "\n");
        }

        public void ClearAndActivate()
        {
            OutputWindowPane pane = this.OutputWindowPane;
            if (pane == null)
            {
                return;
            }

            pane.Clear();
            pane.Activate();
        }
    }
}
